<!DOCTYPE html>
<head>
    <script src="./js/three.js"></script>
    <script src="./js/gltfloader.js"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta charset="UTF-8">
    <style>
        body,html{padding:0;margin:0;background:#000;width:100vw;height:100vh;overflow:hidden;}
        .act {float:left;background:#fff;padding:5px;font-size:12px;border-radius:10px;margin:2px;font-family: Verdana, Geneva, Tahoma, sans-serif;}
        * {box-sizing: border-box;user-select: none;}
    </style>
    <script src="https://cdn.bootcss.com/vConsole/3.3.4/vconsole.min.js"></script>
    <script>
        localStorage.setItem('vConsole_switch_x', 250)

localStorage.setItem('vConsole_switch_y', 250)
        new VConsole();
    </script>
</head>
<body>
    <div style="background:url(./res/big_bg.jpg) no-repeat center center;background-size:cover;position:fixed;top:-23vw;left:0;bottom:0;right:0;z-index:0;"></div>
    <div id="roof" style="background:rgba(255,0,0,0);position:fixed;top:0;left:0;right:0;bottom:0;z-index:9;"></div>
    <canvas id="c" style="position: fixed;z-index:1;transform: scale(0.2);transform-origin: top  left;top:0;left:0;"></canvas>
    <div id="anim" oncontextmenu="event.preventDefault()" style="position: fixed;z-index:999;width:100vw;text-align:center;height:40vh;bottom:0;background:rgba(0,0,0,0.5);left:200vw;">
        <div style="width:100vw;margin:0 20px 40px 0;">
            <div style="font-size:14px;color:#fff;float:left;margin:8px 0 0 12px;">选择动画</div>
            <div style="float:right;background:#f60;padding:5px 10px;border-radius:10px;font-size:12px;margin-top:5px;color:#fff;margin-right:5px;" onclick="document.getElementById('anim').style.left='200vw';window.actStart=false">关闭</div>
        </div>
        <div id="sel" style="margin:10px;overflow:scroll;overflow-x:hidden;width:96vw;height:34vh;">
            
        </div>
    </div>
    
    <div style="display:flex;width:100vw;height:106px;position: fixed;bottom:60px;left:0;padding:10px 15px;color:#fff;z-index:99999;text-align:center;">
        <div ontouchstart="showMic();event.preventDefault();return false;" oncontextmenu="event.preventDefault()"  ontouchend="hideMic();event.preventDefault();return false" style="width:80px;height:80px;background: #f60;color:#fff;border-radius:120px;margin-left:calc(50vw - 55px);">
            <svg style="margin-top:12px;user-select: none;" width="50" height="50" t="1680213719458" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2767" width="24" height="24"><path d="M516.266667 657.066667c78.933333 0 142.933333-64 142.933333-142.933334V217.6a142.933333 142.933333 0 0 0-285.866667 0v296.533333c0 78.933333 64 142.933333 142.933334 142.933334z m-78.933334-439.466667c0-42.666667 36.266667-78.933333 78.933334-78.933333s78.933333 36.266667 78.933333 78.933333v296.533333c0 42.666667-36.266667 78.933333-78.933333 78.933334s-78.933333-36.266667-78.933334-78.933334V217.6z" fill="#ffffff" p-id="2768"></path><path d="M774.4 409.6c-17.066667 0-32 14.933333-32 32v74.666667c0 125.866667-102.4 228.266667-228.266667 228.266666S288 640 288 514.133333v-74.666666c0-17.066667-14.933333-32-32-32s-32 14.933333-32 32v74.666666c0 149.333333 113.066667 273.066667 260.266667 290.133334v85.333333h-117.333334c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h296.533334c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32h-117.333334v-85.333333c145.066667-14.933333 260.266667-140.8 260.266667-290.133334v-74.666666c0-17.066667-12.8-29.866667-32-29.866667z" fill="#ffffff" p-id="2769"></path></svg>
        </div>
    </div>
    <div oncontextmenu="event.preventDefault()" style="display:flex;width:100vw;height:66px;position: fixed;bottom:0;left:0;padding:10px 15px;color:#fff;z-index:99999;text-align:center;">
        <!-- <div onpointerdown="showMic();event.preventDefault()" oncontextmenu="event.preventDefault()"  onpointerup="hideMic();event.preventDefault()" style="width:40px;height:42px;background: #f60;color:#fff;border-radius: 30px;margin-right:10px;">
            <svg style="margin-top:8px;user-select: none;" t="1680213719458" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2767" width="24" height="24"><path d="M516.266667 657.066667c78.933333 0 142.933333-64 142.933333-142.933334V217.6a142.933333 142.933333 0 0 0-285.866667 0v296.533333c0 78.933333 64 142.933333 142.933334 142.933334z m-78.933334-439.466667c0-42.666667 36.266667-78.933333 78.933334-78.933333s78.933333 36.266667 78.933333 78.933333v296.533333c0 42.666667-36.266667 78.933333-78.933333 78.933334s-78.933333-36.266667-78.933334-78.933334V217.6z" fill="#ffffff" p-id="2768"></path><path d="M774.4 409.6c-17.066667 0-32 14.933333-32 32v74.666667c0 125.866667-102.4 228.266667-228.266667 228.266666S288 640 288 514.133333v-74.666666c0-17.066667-14.933333-32-32-32s-32 14.933333-32 32v74.666666c0 149.333333 113.066667 273.066667 260.266667 290.133334v85.333333h-117.333334c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h296.533334c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32h-117.333334v-85.333333c145.066667-14.933333 260.266667-140.8 260.266667-290.133334v-74.666666c0-17.066667-12.8-29.866667-32-29.866667z" fill="#ffffff" p-id="2769"></path></svg>
        </div> -->
        <input id="text" style="flex:1;border:1px solid #fff;background:#fff;border-radius:20px;height:40px;padding:0 10px;outline: none;font-size:14px;" placeholder="请输入对话文字.."/>
        <div onclick="send()" style="width:80px;height:44px;background: #f60;color:#fff;border-radius: 30px;margin-left:10px;line-height:44px;">
            发送
        </div>
    </div>
    <div id="chat" oncontextmenu="event.preventDefault()" style="width:100vw;height:15vh;position: fixed;bottom:160px;left:0;padding:10px 15px;color:#fff;z-index:9998;overflow: scroll;overflow-x: hidden;">
        
    </div>
    <div id="mic" oncontextmenu="event.preventDefault()" style="display:none;position: fixed;top:0;left:0;width:100vw;height:100vh;background:rgba(0,0,0,0.7);z-index: 9999;">
        <svg style="width:30vw;height:30vw;position:fixed;top:40vh;left:50vw;transform: translate(-50%,-50%);" version="1.1" id="L3" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
            <circle fill="none" stroke="#fff" stroke-width="4" cx="50" cy="50" r="44" style="opacity:0.5;"></circle>
              <circle fill="#fff" stroke="#e74c3c" stroke-width="3" cx="8" cy="54" r="6">
                <animateTransform attributeName="transform" dur="2s" type="rotate" from="0 50 48" to="360 50 52" repeatCount="indefinite"></animateTransform>
                
              </circle>
         </svg>
         <svg style="width:60px;height:60px;position:fixed;top:40vh;left:50vw;transform:translate(-50%,-50%);"  viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2767" width="24" height="24"><path d="M516.266667 657.066667c78.933333 0 142.933333-64 142.933333-142.933334V217.6a142.933333 142.933333 0 0 0-285.866667 0v296.533333c0 78.933333 64 142.933333 142.933334 142.933334z m-78.933334-439.466667c0-42.666667 36.266667-78.933333 78.933334-78.933333s78.933333 36.266667 78.933333 78.933333v296.533333c0 42.666667-36.266667 78.933333-78.933333 78.933334s-78.933333-36.266667-78.933334-78.933334V217.6z" fill="#ffffff" p-id="2768"></path><path d="M774.4 409.6c-17.066667 0-32 14.933333-32 32v74.666667c0 125.866667-102.4 228.266667-228.266667 228.266666S288 640 288 514.133333v-74.666666c0-17.066667-14.933333-32-32-32s-32 14.933333-32 32v74.666666c0 149.333333 113.066667 273.066667 260.266667 290.133334v85.333333h-117.333334c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h296.533334c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32h-117.333334v-85.333333c145.066667-14.933333 260.266667-140.8 260.266667-290.133334v-74.666666c0-17.066667-12.8-29.866667-32-29.866667z" fill="#ffffff" p-id="2769"></path></svg>
         <div id="time" style="width:60px;height:60px;position:fixed;top:52vh;left:50vw;transform:translate(-50%,-50%);color:#fff;font-size:24px;text-align: center;">
            30s
         </div>
         
    </div>
    <div id="loading" style="position: fixed;z-index:9999;width:100vw;height:100vh;background:rgba(0,0,0,0.8) url(./res/loading.svg) no-repeat center center;background-size:20vw auto;color:#fff;text-align:center;">
       <div style="margin-top:calc(50vh + 15vw)"> </div>
    </div>
    <img style="position:absolute;top:10px;left:0;width:20vw;" src="./res/logo.png"/>
    <audio id="ad" autoplay="autoplay" preload="auto" src=""></audio>
    
</body>
<script>
    document.oncontextmenu = function(e){
        e.preventDefault();
        return false;
    }
    var cfg = {
        name:"大眼鹿",
        recordSpan:10,
        server:"https://1576889560723912.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/xm-app-fc-l6z71c9d/xm-fc-main/",
        server:"https://drive-java.4ukids.cn/",
    }
    var t = cfg.recordSpan;
    function timer(callback){
        if (t <= 0) return callback&&callback();
        document.getElementById("time").innerHTML = `${t}s`
        t -- ;
        setTimeout(()=>{timer(callback)},1000);
    }
    function playAnim(sound){
        console.log("开始播放")
        if(window.obj){
            window.obj.rotation.y = 0.4
        }
        console.log(sound);
        if(window.audio==null){
            window.audio = document.getElementById("ad")
            audio.addEventListener("play", function() {
                window.idel.stop();
                window.speaking.stop();
                window.speaking.play()
                setTimeout(()=>{
                    window.speaking.stop();
                    window.idel.play()
                },8000)
            });

        }
        window.audio.src = sound;
        window.audio.loop = false;
        window.audio.play();
    }
    function stopAnim(){
        console.log("结束播放")
    }
    var startTime = 0
    async function showMic(){
        if(!window.first){
            var m  = await getMedia(async (base64)=>{
            });
            window.first = true;
            return ;
        }
        var m  = await getMedia(async (base64)=>{
            //console.log("获得的对象",base64);
            var r = await $post(cfg.server+"?act=get_text",{sound:base64})
            document.getElementById("loading").style.display = "none";
            if(r.msg!="ok"){
                return alert(r.info);
            }
            console.log("返回文字",r.result.text)
            document.getElementById("text").value = r.result.text;
            document.getElementById("loading").style.display = "none";
            send();
        });
        window.m = m;
        m.start();
        startTime = Date.now();
        document.getElementById("mic").style.display = "block";
        t = cfg.recordSpan;
        timer(()=>{
            hideMic();
        });
    }
    function hideMic(){
        if(Date.now() - startTime <= 1000){
            document.getElementById("mic").style.display = "none";
            console.log("录音小于1s!");
            window.m.stop();
        }
        if(document.getElementById("mic").style.display == "none") return;
        document.getElementById("mic").style.display = "none";
        document.getElementById("loading").style.display = "block";
        window.m.stop();
    }
    var list = []
    function add(name,text){
        if(list.length>=100) list.shift();
        list.push({name:name,text:text});
        var html = []
        for(var i =0;i<list.length;i++){
            html.push(`<div><b style="color:#f60">${list[i].name}</b>: ${list[i].text}</div>`)
        }
        document.getElementById("chat").innerHTML = html.join("");
        setTimeout(() => {
            document.getElementById("chat").scrollTop = 9999999;
        }, (1));
    }
    async function send(){
        if(document.getElementById("text").value == "") return;
        document.getElementById("loading").style.display = "block";

        
        var r =  await $post(cfg.server+"?act=get_answer",{text:document.getElementById("text").value})
        console.log("666666",r);
        if(r.msg != "ok"){ 
        document.getElementById("loading").style.display = "none";return alert(r.info)}
        add("我",document.getElementById("text").value);
        add(cfg.name,r.result.text);
        document.getElementById("text").value ="";
        document.getElementById("loading").style.display = "none";
         playAnim(r.result.sound);
        // stopAnim();

        

        // setTimeout(()=>{
        //     add("我",document.getElementById("text").value);
        //     // 拿到音频开始播放
        //     playAnim();
        //     add(cfg.name,"我正在思考,请稍候...");
        //     stopAnim();
        // },1000);
    }
    
    var scene = new THREE.Scene();
  
    // scene.add(mesh); //网格模型添加到场景中
    //var point = new THREE.PointLight(0x000000);
    // point.position.set(400, 200, 300); //点光源位置
    // scene.add(point); //点光源添加到场景中
    //给场景添加太阳光
    let Sun = new THREE.DirectionalLight(0xffffff, 0.8);
    Sun.position.set(20, 20, 20);
    Sun.castShadow = true;
     //设置相机渲染面积
    Sun.shadow.camera.near = 0.01;
    Sun.shadow.camera.far = 60;
    Sun.shadow.camera.top = 22;
    Sun.shadow.camera.bottom = -22;
    Sun.shadow.camera.left = -35;
    Sun.shadow.camera.right = 35;
    // //设置阴影分辨率
    Sun.shadow.mapSize.width = 2048;  // default
    Sun.shadow.mapSize.height = 2048; // default
    //阴影限制
    Sun.shadow.radius = 1;
    scene.add(Sun);
    //环境光
    var ambient = new THREE.AmbientLight(0xffffff);
    scene.add(ambient);
    var width = document.body.offsetWidth; //窗口宽度
    var height = document.body.offsetHeight; //窗口高度
    var k = width / height; //窗口宽高比
    var s = 200; //三维场景显示范围控制系数，系数越大，显示的范围越大
    //创建相机对象
    var camera = new THREE.PerspectiveCamera(45, k , 1, 1000);
    camera.position.set(200, 150, 500); //设置相机位置
    camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
    /**
     * 创建渲染器对象
     */
    var renderer = new THREE.WebGLRenderer({antialias:true,alpha:true,canvas:document.getElementById("c")});
    renderer.setSize(width*5, height*5);//设置渲染区域尺寸
    renderer.setClearColor(0xb9d3ff, 0); //设置背景颜色
    // document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
    // renderer.domElement.style.position = "fixed";
    // renderer.domElement.style.zIndex = 1;
    // renderer.shadowMapEnabled = true;
    //执行渲染操作   指定场景、相机作为参数

    let obj = null;
    // 加载 glTF 格式的模型
    let loader = new THREE.GLTFLoader();/*实例化加载器*/
    var clock = new THREE.Clock();
    let mixer  = null;
    let lastAction = null;
    function play(num){
        if(num < 0) return;
        lastAction && lastAction.stop();
        if(mixer){
            lastAction = mixer.clipAction(anims[num-1])
            lastAction.play(); 
        }
        window.isStart = false;
    }
    function clearRotate(){
        if(!obj) return;
        obj.rotation.y =3
    }
    let anims = []

    //加载模型
    loader.load('https://booisrs.oss-cn-hangzhou.aliyuncs.com/_4uchat/new.glb',function (object) {
         console.table(object);
         object.scene.position.y = -80;
         scene.add(object.scene);
         obj = object.scene;
         obj.scale.x = 160
         obj.scale.y = 160
         obj.scale.z = 160
         obj.rotation.y= 0.4;
        document.getElementById('loading').style.display = 'none';
        window.obj = obj;
        // console.log("ok")

        anims = object.animations
        mixer = new THREE.AnimationMixer(object.scene)
        window.idel = mixer.clipAction(anims[0])
        window.speaking = mixer.clipAction(anims[1])
        window.idel.play();
    
        document.getElementById("loading").style.display = "none";
    },function (xhr) {

        console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );

    },function (error) {

        console.log('load error!'+error);

    })

    window.dr = 1;
    let rd  = ()=>{
        //if(!window.isStart && obj &&!window.actStart) obj.rotateY(window.dr*0.01)
        renderer.render(scene, camera);
        var delta = clock.getDelta();
        mixer && mixer.update( delta)
        requestAnimationFrame(rd)
    } 
    requestAnimationFrame(rd);
    document.body.addEventListener("touchstart",(e)=>{
         window.startX = e.touches[0].clientX;
         window.startY = e.touches[0].clientY;
         window.isStart = true;
    })
    document.getElementById("roof").addEventListener("touchmove",(e)=>{
        let s =  window.startX  - e.touches[0].clientX;
        window.dr = (s>0?-1:1)
        obj.rotation.y += (window.dr*0.2)
        window.startX = e.touches[0].clientX
    })
    document.getElementById("roof").addEventListener("touchend",(e)=>{
        
        window.isStart = false;
    })

    function getMedia(callback){
        return new Promise((ok)=>{

            navigator.mediaDevices.getUserMedia({audio: true})
            .then(stream => {
                var opt = {
                    audioBitsPerSecond : 128000,
                    sampleRate : 16000,
                    numberOfChannels: 1
                }
                const mediaRecorder = new MediaRecorder(stream,opt);
                let chunks = [];

                mediaRecorder.addEventListener('dataavailable', event => {
                chunks.push(event.data);
                });

                mediaRecorder.addEventListener('stop', () => {
                    const blob = new Blob(chunks, {type: 'audio/webm'});
                    let a = new FileReader();
                    a.onload = function (e) {
                        //console.log("音频数据",e.target.result)
                        callback(e.target.result);
                    }
                    a.readAsDataURL(blob);
                // 将url发送到服务器进行处理
                });
                ok(mediaRecorder)
                // mediaRecorder.start();
                // mediaRecorder.stop();
            })
            .catch(error => {
                alert("获取录音权限失败,请重试！")
                console.log(error);
            });

        });
    }
    // let t = setInterval(() => {
    //     if(obj){
    //         obj.rotateY(0.01)
    //         renderer.render(scene, camera);
    //         // clearInterval(t);
    //     }
    // }, 17);
    function playBase64Audio(base64Data) {;
        var blob = new Blob([new Uint8Array(binaryData)], {type: 'audio/mp3'});
        var url = URL.createObjectURL(blob);

        var audio = new Audio();
        audio.src = url;
        audio.play();
    }
    let $post = function(url,postData,okFn,errFn){
    return new Promise((resolve)=>{
        this.brk = false;
        okFn = typeof(okFn) == "function"?okFn:()=>{};
        errFn = typeof(errFn) == "function"?errFn:()=>{};

        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = ()=> {
            if (xhr.readyState == 4) {
                xhr.onreadystatechange = ()=>{};
                this.brk = true;
                if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
                    let data = xhr.responseText;
                    if(data.trim().startsWith("{") && data.trim().endsWith("}")){
                        try{
                            var j = JSON.parse(data);
                            okFn(j,xhr);
                            resolve(j);
                        }catch (e) {
                            console.warn(e);
                            okFn(data,xhr);
                            resolve({"msg":"err_json_err","info":"和我说话的人太多了,请再试一次!","err":data});
                        }
                    }else{
                        okFn(data, xhr);
                        resolve({"msg":"err_json_err","info":"和我说话的人太多了,请再试一次!","err":data});
                        //resolve({"msg":"ok","info":"","result":data});
                    }
                } else if (0 == xhr.status) {
                    errFn("跨域请求失败", xhr);
                    resolve({"msg":"err_cors","info":"服务器繁忙,请再试一次!!"});
                } else {
                    errFn(xhr.statusText, xhr);
                    resolve({"msg":"err_server_err","info":"和我说话的人太多了,请一会再试一次!"});
                }
            }
        };
        xhr.open("POST", url, true);
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
        if(typeof(postData) == "string"){xhr.send(postData);return;}
        if(typeof(postData) != "object"){xhr.send("");return;}
        let r = "";
        for(let x in postData){
            r+= `&${x}=${ encodeURIComponent(postData[x])}`
        }
        xhr.send(r);
    });
};
</script>
</html>